/*
 * Copyright (C) 2017-2021
 * All rights reserved, Designed By
 * Copyright authorization contact 18814114118
 */
package com.shop.cereshop.agent.service.order.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.shop.cereshop.agent.dao.order.AgentOrderDAO;
import com.shop.cereshop.agent.page.order.AgentOrderVO;
import com.shop.cereshop.agent.page.product.CartVO;
import com.shop.cereshop.agent.page.user.CereAgentUserVO;
import com.shop.cereshop.agent.page.wallet.AgentWalletVO;
import com.shop.cereshop.agent.param.order.OrderGetByIdDTO;
import com.shop.cereshop.agent.param.order.OrderPayDTO;
import com.shop.cereshop.agent.service.order.AgentOrderProductService;
import com.shop.cereshop.agent.service.order.AgentOrderProductAttributeService;
import com.shop.cereshop.agent.page.product.AgentProductSkuVO;
import com.shop.cereshop.agent.page.product.SkuAttributeVO;
import com.shop.cereshop.agent.service.order.AgentOrderService;
import com.shop.cereshop.agent.service.stock.AgentStockService;
import com.shop.cereshop.agent.service.redis.CereRedisKeyService;
import com.shop.cereshop.agent.redis.api.StringRedisService;
import com.shop.cereshop.agent.service.voucher.AgentVoucherService;
import com.shop.cereshop.agent.service.voucher.AgentVoucherTransactionService;
import com.shop.cereshop.agent.service.voucher.AgentVoucherUserService;
import com.shop.cereshop.agent.service.wallet.AgentWalletService;
import com.shop.cereshop.agent.service.wallet.AgentWalletTransactionService;
import com.shop.cereshop.commons.constant.StringEnum;
import com.shop.cereshop.commons.domain.agent.CereAgentVoucherTransaction;
import com.shop.cereshop.commons.domain.agent.CereAgentVoucherUser;
import com.shop.cereshop.commons.domain.wallet.CereAgentWallet;
import com.shop.cereshop.commons.domain.wallet.CereAgentWalletTransaction;
import com.shop.cereshop.commons.utils.TimeUtils;
import com.shop.cereshop.commons.constant.CoReturnFormat;
import com.shop.cereshop.commons.constant.IntegerEnum;
import com.shop.cereshop.commons.domain.order.CereAgentOrder;
import com.shop.cereshop.commons.domain.order.CereAgentOrderProduct;
import com.shop.cereshop.commons.domain.order.CereAgentOrderProductAttribute;
import com.shop.cereshop.commons.exception.CoBusinessException;
import com.shop.cereshop.commons.utils.EmptyUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.ArrayList;

import com.shop.cereshop.agent.param.settlement.SettlementDTO;
import com.shop.cereshop.agent.param.settlement.AgentProductSku;
import com.shop.cereshop.agent.param.order.OrderSubmitDTO;
import com.shop.cereshop.agent.page.settlement.SettlementVO;
import com.shop.cereshop.agent.page.settlement.SettlementProductVO;
import com.shop.cereshop.commons.domain.agentProduct.CereAgentProductSku;
import com.shop.cereshop.agent.dao.product.AgentProductSkuDAO;

/**
 * 代理商订单Service实现
 *
 * @author lx
 */
@Slf4j
@Service
public class AgentOrderServiceImpl extends ServiceImpl<AgentOrderDAO, CereAgentOrder> implements AgentOrderService {

  @Resource
  private AgentOrderDAO agentOrderDAO;

  @Resource
  private AgentWalletService agentWalletService;

  @Resource
  private AgentOrderService agentOrderService;

  @Resource
  private AgentOrderProductService agentOrderProductService;

  @Resource
  private AgentOrderProductAttributeService agentOrderProductAttributeService;

  @Autowired
  private AgentStockService agentStockService;

  @Autowired
  private CereRedisKeyService cereRedisKeyService;

  @Autowired
  private StringRedisService stringRedisService;

  @Resource
  private AgentProductSkuDAO agentProductSkuDAO;

  @Resource
  private AgentWalletTransactionService agentWalletTransactionService;

  @Resource
  private AgentVoucherUserService agentVoucherUserService ;

  @Resource
  private AgentVoucherTransactionService agentVoucherTransactionService ;

  @Override
  @Transactional
  public void cancelOrder(OrderGetByIdDTO param, Long agentUserId) throws CoBusinessException {
    // 校验订单状态
    CereAgentOrder cereAgentOrder = lambdaQuery().eq(CereAgentOrder::getOrderId, param.getOrderId())
        .eq(CereAgentOrder::getAgentUserId, agentUserId)
        .eq(CereAgentOrder::getState, IntegerEnum.AGENT_ORDER_STATE_WAIT_PAY.getCode())
        .one();
    if (cereAgentOrder == null) {
      throw new CoBusinessException(CoReturnFormat.ORDER_NOT_TAKE);
    }
    LocalDateTime now = LocalDateTime.now();
    // 修改订单状态为已取消
    lambdaUpdate().eq(CereAgentOrder::getOrderId, param.getOrderId())
        .set(CereAgentOrder::getState, IntegerEnum.ORDER_STOP.getCode())
        .set(CereAgentOrder::getUpdateTime, now)
        .set(CereAgentOrder::getCancelTime, now)
        .update();
    // 根据订单id获取商品
    List<CereAgentOrderProduct> list = agentOrderProductService.lambdaQuery()
        .eq(CereAgentOrderProduct::getOrderId, param.getOrderId())
        .list();
    // 恢复库存数量
    agentStockService.rollbackStockByList(list);
    // 删除订单支付倒计时延时任务
    stringRedisService.delete(StringEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + param.getOrderId());
    cereRedisKeyService.deleteByKey(StringEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + param.getOrderId());
  }

  @Override
  public List<AgentOrderVO> getOrderListByUser(Long agentUserId, Integer orderType, Integer state, Integer page,
      Integer pageSize) {
    // 使用PageHelper处理分页
    PageHelper.startPage(page, pageSize);

    // 查询订单列表根据类type
    List<AgentOrderVO> orderList = agentOrderDAO.queryOrderListByType(agentUserId, orderType, state);

    // 对于常规商品订单，需要查询订单商品信息
    if (orderList != null && !orderList.isEmpty()) {
      for (AgentOrderVO order : orderList) {
        // 对于常规订单（order_type=1），查询订单商品明细
        if (IntegerEnum.ORDER_TYPE_NORMAL.getCode().equals(order.getOrderType())) {
          List<CereAgentOrderProduct> products = agentOrderProductService.lambdaQuery()
              .eq(CereAgentOrderProduct::getOrderId, order.getAgentOrderId())
              .list();
          // 不上throw一个sstream是因为可能不有下拋ProductService，先直接用查到的信息
          if (products != null && !products.isEmpty()) {
            List<CartVO> cartVOList = products.stream()
                .map(product -> {
                  CartVO cartVO = new CartVO();
                  cartVO.setProductName(product.getProductName());
                  cartVO.setProductPrice(product.getProductPrice());
                  cartVO.setProductImage(product.getImage());
                  cartVO.setNumber(product.getNumber());
                  return cartVO;
                })
                .collect(java.util.stream.Collectors.toList());
            order.setProducts(cartVOList);
          }
        }
      }
    }

    return orderList;
  }

  @Override
  @Transactional
  public Long submitOrder(OrderSubmitDTO param, Long agentUserId) throws CoBusinessException, Exception {
    // 验证参数
    if (param == null || EmptyUtils.isEmpty(param.getProducts())) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "订单商品不能为空");
    }

    if (param.getPrice() == null || param.getPrice().compareTo(java.math.BigDecimal.ZERO) <= 0) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "订单金额不能为空或小于0");
    }

    // 创建订单
    CereAgentOrder order = new CereAgentOrder();
    order.setAgentUserId(agentUserId);
    order.setTotalAmount(param.getPrice());
    order.setPayAmount(param.getPrice());
    order.setState(IntegerEnum.AGENT_ORDER_STATE_WAIT_PAY.getCode());
    order.setOrderType(IntegerEnum.ORDER_TYPE_NORMAL.getCode());
    order.setCreateTime(LocalDateTime.now());

    // 保存订单
    boolean saveSuccess = this.save(order);
    if (!saveSuccess) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "创建订单失败");
    }

    // 保存订单商品明细
    if (!EmptyUtils.isEmpty(param.getProducts())) {
      for (AgentProductSku sku : param.getProducts()) {
        if (sku.getSkuId() != null && sku.getNumber() != null && sku.getNumber() > 0) {
          CereAgentOrderProduct orderProduct = new CereAgentOrderProduct();
          orderProduct.setOrderId(order.getOrderId());
          orderProduct.setSkuId(sku.getSkuId());
          orderProduct.setNumber(sku.getNumber());
          agentOrderProductService.save(orderProduct);

          // 保存订单商品规格属性快照
          // 根据skuId查询该SKU的所有规格属性
          CereAgentProductSku agentSku = agentProductSkuDAO.selectById(sku.getSkuId());
          if (agentSku != null) {
            AgentProductSkuVO skuDetail = agentProductSkuDAO.getProductSkuList(agentSku.getAgentProductId())
                .stream()
                .filter(s -> s.getSkuId().equals(sku.getSkuId()))
                .findFirst()
                .orElse(null);

            if (skuDetail != null && !EmptyUtils.isEmpty(skuDetail.getSpecs())) {
              for (SkuAttributeVO attr : skuDetail.getSpecs()) {
                CereAgentOrderProductAttribute attribute = new CereAgentOrderProductAttribute();
                attribute.setOrderProductId(orderProduct.getOrderProductId());
                attribute.setSkuName(attr.getSkuName());
                attribute.setSkuValue(attr.getSkuValue());
                attribute.setValueCode(attr.getValueCode());
                agentOrderProductAttributeService.save(attribute);
              }
            }
          }
        }
      }
    }

    // 设置订单支付倒计时延时任务（30分钟自动取消）
    String orderAutoClosKey = StringEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + order.getOrderId();
    String endTime = TimeUtils.getMinuteAfter(30);
    stringRedisService.set(orderAutoClosKey, 1, 30 * 60 * 1000);
    cereRedisKeyService.add(orderAutoClosKey, endTime);

    // 返回订单ID
    return order.getOrderId();
  }

  @Override
  public SettlementVO getSettlement(SettlementDTO param, Long agentUserId) {
    SettlementVO settlement = new SettlementVO();
    // 新建正常商品集合和失效商品集合
    List<SettlementProductVO> settlementProducts = new ArrayList<>();
    List<SettlementProductVO> invalidProducts = new ArrayList<>();

    // 验证参数
    if (param == null || EmptyUtils.isEmpty(param.getProducts())) {
      settlement.setSettlementProducts(settlementProducts);
      settlement.setInvalidProducts(invalidProducts);
      return settlement;
    }

    // 遍历每一个sku进行库存检查
    for (AgentProductSku sku : param.getProducts()) {
      // 校验参数
      if (sku == null || sku.getSkuId() == null || sku.getNumber() == null || sku.getNumber() <= 0) {
        // 跳过无效参数
        continue;
      }

      // 查询sku信息
      CereAgentProductSku agentProductSku = agentProductSkuDAO.selectById(sku.getSkuId());
      // SKU不存在，跳过
      if (agentProductSku == null) {
        continue;
      }

      SettlementProductVO settlementProduct = new SettlementProductVO();
      settlementProduct.setSkuId(agentProductSku.getSkuId());
      settlementProduct.setPrice(agentProductSku.getPrice());
      settlementProduct.setOriginalPrice(agentProductSku.getOriginalPrice());
      settlementProduct.setStockNumber(agentProductSku.getStockNumber());
      settlementProduct.setNumber(sku.getNumber());

      // 检查库存是否足够
      if (agentProductSku.getStockNumber() != null && agentProductSku.getStockNumber() >= sku.getNumber()) {
        // 正常商品
        settlementProducts.add(settlementProduct);
      } else {
        // 库存不足置灰并一起返回
        invalidProducts.add(settlementProduct);
      }
    }

    settlement.setSettlementProducts(settlementProducts);
    settlement.setInvalidProducts(invalidProducts);
    return settlement;
  }

  @Override
  public void deleteOrder(OrderGetByIdDTO param, CereAgentUserVO user) throws CoBusinessException {
    boolean remove = lambdaUpdate().eq(CereAgentOrder::getOrderId, param.getOrderId())
        .eq(CereAgentOrder::getAgentUserId, user.getAgentUserId())
        .remove();
    if (!remove) {
      throw new CoBusinessException(CoReturnFormat.FAIL);
    }
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void agentPayOrder(OrderPayDTO param, Long agentUserId) throws CoBusinessException {
    //查询订单信息
    CereAgentOrder cereAgentOrder = agentOrderService.lambdaQuery()
            .eq(CereAgentOrder::getOrderId, param.getOrderId())
            .one();
    if (cereAgentOrder == null) {
      throw new CoBusinessException(CoReturnFormat.FAIL, "订单不存在");
    }
    //不同支付方式支付
    if (IntegerEnum.AGENT_PAY_TYPE_WALLET.getCode().equals(param.getPayType())) {
      //查询用户钱包信息
      AgentWalletVO wallet = agentWalletService.getWallet(agentUserId, IntegerEnum.ROLE_TYPE_AGENT.getCode());
      if (wallet == null) {
        throw new CoBusinessException(CoReturnFormat.FAIL, "用户钱包不存在");
      }
      if (wallet.getBalance().compareTo(cereAgentOrder.getTotalAmount()) < 0) {
        throw new CoBusinessException(CoReturnFormat.FAIL, "用户余额不足");
      }
      //计算新的余额
      BigDecimal newBalance = wallet.getBalance().subtract(cereAgentOrder.getTotalAmount());
      boolean update = agentWalletService.lambdaUpdate()
              .eq(CereAgentWallet::getWalletId, wallet.getWalletId())
              .set(CereAgentWallet::getBalance, newBalance)
              .update();
      if (!update) {
        throw new CoBusinessException(CoReturnFormat.FAIL, "支付失败");
      }
      //新增钱包流水
      CereAgentWalletTransaction build = CereAgentWalletTransaction.builder()
              .agentUserId(agentUserId)
              .transactionType(param.getPayType())
              .amount(cereAgentOrder.getTotalAmount())
              .balanceBefore(wallet.getBalance())
              .balanceAfter(newBalance)
              .targetId(cereAgentOrder.getOrderId())
              .description("余额支付订单")
              .remark("支付订单")
              .roleType(IntegerEnum.ROLE_TYPE_AGENT.getCode())
              .createTime(LocalDateTime.now())
              .roleType(IntegerEnum.ROLE_TYPE_AGENT.getCode())
              .build();
      agentWalletTransactionService.save(build);
    } else if (IntegerEnum.AGENT_PAY_TYPE_VOUCHER.getCode().equals(param.getPayType())) {
      //查询代金券信息
      CereAgentVoucherUser agentVoucherUser = agentVoucherUserService.lambdaQuery()
              .eq(CereAgentVoucherUser::getAgentUserId, agentUserId)
              .one();
      if (agentVoucherUser == null) {
        throw new CoBusinessException(CoReturnFormat.FAIL, "代金券不存在");
      }
      if (agentVoucherUser.getRemainingAmount().compareTo(cereAgentOrder.getTotalAmount()) < 0) {
        throw new CoBusinessException(CoReturnFormat.FAIL, "代金券余额不足");
      }
      //计算新的余额
      BigDecimal newBalance = agentVoucherUser.getRemainingAmount().subtract(cereAgentOrder.getTotalAmount());
      agentVoucherUserService.lambdaUpdate()
              .eq(CereAgentVoucherUser::getVoucherUserId, agentVoucherUser.getVoucherUserId())
              .set(CereAgentVoucherUser::getRemainingAmount, newBalance)
              .update();
      //新增代金券流水
      CereAgentVoucherTransaction voucherTransaction = CereAgentVoucherTransaction.builder()
              .agentUserId(agentUserId)
              .balanceBefore(agentVoucherUser.getRemainingAmount())
              .balanceAfter(newBalance)
              .orderId(cereAgentOrder.getOrderId())
              .description("代金券支付订单")
              .build();
      agentVoucherTransactionService.save(voucherTransaction);
    }
    //修改订单状态
    agentOrderService.lambdaUpdate()
            .eq(CereAgentOrder::getOrderId, param.getOrderId())
            .set(CereAgentOrder::getState, IntegerEnum.ORDER_PAY_SUCCESS.getCode())
            .update();
  }

  //todo:需要写一个单独方法用于代理商每次消费都需要给上级代理商分润
}
